package com.start.common.mybaitsplus;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;

@Slf4j
@Configuration
@AutoConfigureAfter({SqlSessionFactory.class})
public class StartMyBaitsPlusTypeHandler {
    private final SqlSessionFactory sqlSessionFactory;
    private TypeHandlerRegistry typeHandlerRegistry;
    private Method typeHandlerRegisterMethod;

    public StartMyBaitsPlusTypeHandler(ObjectProvider<SqlSessionFactory> sqlSessionFactoryObjectProvider) {
        this.sqlSessionFactory = sqlSessionFactoryObjectProvider.getIfAvailable();
        initGlobalEnum();
    }

    private void initGlobalEnum() {
        if (sqlSessionFactory == null) {
            log.warn("全局枚举注册无法使用");
            return;
        }
        this.typeHandlerRegistry = this.sqlSessionFactory.getConfiguration().getTypeHandlerRegistry();
        try {
            typeHandlerRegisterMethod = TypeHandlerRegistry.class.getDeclaredMethod("register", Type.class, TypeHandler.class);
            typeHandlerRegisterMethod.setAccessible(true);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    /**
     * 注册枚举类型
     *
     * @param javaType
     * @param typeHandler
     * @param <T>
     */
    public <T> void registerTypeHandler(Type javaType, TypeHandler<? extends T> typeHandler) {
        if (sqlSessionFactory == null || typeHandlerRegisterMethod == null) {
            log.warn("全局枚举注册无法使用");
            return;
        }
        try {
            typeHandlerRegisterMethod.invoke(typeHandlerRegistry, javaType, typeHandler);
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
            log.error("枚举注册失败:" + javaType);
        }

    }
}
